/*
 * Copyright 2007 Stefan Arentz <http://stefan.arentz.nl>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.sateh.spaces;

import javax.transaction.Transaction;
import java.io.Serializable;

public interface Space
{
    /**
     * A write places a copy of an entry into the given JavaSpaces service. The Entry passed to the write
     * is not affected by the operation. Each write operation places a new Entry into the specfied space,
     * even if the same Entry object is used in more than one write.
     * <p/>
     * Each write invocation returns a {@link Lease} object that is lease milliseconds long. If the requested
     * time is longer than the space is willing to grant, you will het a lease with a reduced time. When the
     * lease expires, the entry is removed from the space. You will get an IllegalArgumentException if the lease
     * time requested is negative.
     * <p/>
     * If a write return without throwing an exception, that entry is committed to the space, possibly within
     * a transaction. If a {@link java.rmi.RemoteException} is thrown, the write may or may not have been
     * successful. If any other exception is thrown, the entry was not written into the space.
     * <p/>
     * Writing an entry into a space might generate notifications to registered objects.
     * <p/>
     * When a transaction is specified then writing an entry into the space, the entry is not seen or accessible
     * outside of the transaction (that is to operations that don't occur under the same transaction) until the
     * transaction commits. If the transaction commits, then all the entries written under the transaction (and
     * not later taken within the same transaction) become visible in the entire space. However, if the
     * transaction aborts, the entries written under the transaction are removed and never become visible.
     *
     * @param object
     * @param lease
     * @return
     * @throws SpaceException
     */

    Lease write(Object object, Transaction tx, long lease)
        throws SpaceException;

    // Read

    /**
     * Search the JavaSpaces services for an entry that matches the specified class. If a match is found, a
     * reference to a copy of the matching entry is returned. If no match is found, null is returned. Passing
     * Object's class will return any entry.
     * <p/>
     * Any matching entry can be returned. Successive read requests with the same template in the same
     * JavaSpaces service may or may not return equivalent objects, even if no intervening modifications have
     * been made to the space. Each invocation of read may return a new object even if the same entry is matched
     * in the the JavaSpaces service.
     * <p/>
     * A read request will return a matching entry, or null if there is no matching entry in the space. If the
     * only possible matches for the template have conflicting locks from one or more transactions, the timeout
     * value specifies how long the client is willing to wait for interfering transactions to settle before
     * returning a value. If at the end of that time no value can be returned that owuld not interfere with
     * transactional state, null is returned. Note that, due to the remote nature of JavaSpaces services, read
     * may throw a {@link java.rmi.RemoteException} if the network or server fails prior to the timeout expiration.
     * <p/>
     * The read request will block until a matching entry is found or until transactions settle, whichever is
     * longer, up to the timeout period.
     * <p/>
     * When an entry is read from the space under a transaction, the entry can come from entries written under
     * the transaction, or entries in the space.
     *
     * @param clazz
     * @param timeout
     * @return
     * @throws SpaceException
     */

    <T> T read(Class<T> clazz, Transaction tx, long timeout)
        throws SpaceException, UnusableEntryException;

    <T> T readIfExists(Class<T> clazz, Transaction tx)
        throws SpaceException, UnusableEntryException;

    <T> T read(T objectTemplate, Transaction tx, long timeout)
        throws SpaceException, UnusableEntryException;

    <T> T readIfExists(T objectTemplate, Transaction tx)
        throws SpaceException, UnusableEntryException;

    // Take

    /**
     * When an entry is taken from the space under a transaction, the entry can come from entries written under
     * the same transaction, or entries in the space. If the transaction aborts then the entries taken under the
     * transaction are returned to the space. In effect, after the abort the space reflects that the operations
     * never occurred.
     *
     * @param clazz
     * @param tx
     * @param timeout
     * @return
     * @throws SpaceException
     */

    <T> T take(Class<T> clazz, Transaction tx, long timeout)
        throws SpaceException, UnusableEntryException;

    <T> T takeIfExists(Class<T> clazz, Transaction tx)
        throws SpaceException, UnusableEntryException;

    <T> T take(T objectTemplate, Transaction tx, long timeout)
        throws SpaceException, UnusableEntryException;

    <T> T takeIfExists(T objectTemplate, Transaction tx)
        throws SpaceException, UnusableEntryException;

    // Count

    /**
     *
     * @param clazz
     * @return
     * @throws SpaceException
     */

    long count(Class<? extends Serializable> clazz)
        throws SpaceException;

    /**
     *
     * @param objectTemplate
     * @return
     * @throws SpaceException
     */

    long count(Serializable objectTemplate)
        throws SpaceException;
}
